/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thienloc.omap.controller.report;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thienloc.omap.entity.TinhThanh;
import com.thienloc.omap.entity.report.MoStatistic;
import com.thienloc.omap.session.RequestQueueFacade;
import com.thienloc.omap.session.RequestQueueHistFacade;
import com.thienloc.omap.session.TinhThanhFacade;
import com.thienloc.omap.util.Constant;
import com.thienloc.omap.util.JsfUtil;
import java.io.FileReader;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
@ManagedBean
@ViewScoped
public class MoProductionBean implements Serializable {

    @EJB
    private RequestQueueFacade requestQueueFacade;
    @EJB
    private RequestQueueHistFacade requestQueueHistFacade;
    @EJB
    private TinhThanhFacade tinhThanhFacade;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private Date startTime = DateTime.now().withTimeAtStartOfDay().toDate();
    private Date endTime = DateTime.now().withTime(23, 59, 59, 0).toDate();
    private List<MoStatistic> moProductions;
    private List<MoStatistic> moSummaryProductions;
    private List<String> deliverProviders;

    public void search() {
        try {
            endTime.setHours(23);
            endTime.setMinutes(59);
            endTime.setSeconds(59);
            //tao map de truy xuat nhanh hon
            Map<String, TinhThanh> provinceMap = Maps.newHashMap();
            List<TinhThanh> allProvinces = tinhThanhFacade.findAll();
            for (TinhThanh province : allProvinces) {
                provinceMap.put(province.getMaTinh(), province);
            }

            Splitter splitter = Splitter.on(',').trimResults().omitEmptyStrings();
            Properties properties = new Properties();
            properties.load(new FileReader(Constant.CONFIG_FILE_PATH));
            final List<String> syntaxOrders = Lists.newArrayList(splitter.split(properties.getProperty("moProductionSyntaxOrder", "")));
            Map<String, Integer> moSummaryMap = Maps.newTreeMap();
            for (String syntaxOrder : syntaxOrders) {
                moSummaryMap.put(syntaxOrder, 0);
            }

            Map<String, Integer> moProductionMap = requestQueueFacade.countMoProduction(startTime, endTime, deliverProviders);
            logger.debug("Found {} MO", moProductionMap.size());

            Map<String, Integer> moProductionHistMap = requestQueueHistFacade.countMoProduction(startTime, endTime, deliverProviders);
            Set<String> moHistSet = moProductionHistMap.keySet();
            for (String mo : moHistSet) {
                int count = moProductionHistMap.get(mo);
                if (moProductionMap.containsKey(mo)) {
                    count += moProductionMap.get(mo);
                }
                moProductionMap.put(mo, count);
            }

            logger.debug("Found total {} MO", moProductionMap.size());
            Set<Map.Entry<String, Integer>> entrySet = moProductionMap.entrySet();
            moProductions = Lists.newArrayListWithCapacity(entrySet.size());

            //load nonLotteryServices
            List<String> nonLotteryServices = Lists.newArrayList(splitter.split(properties.getProperty("moProduction.nonLotteryServices", "TIP,TC,HUY")));

            //load similar syntaxes
            List<String> primarySyntaxs = Lists.newArrayList(splitter.split(properties.getProperty("sameSyntax.primary", "S,A,T,N,TIP")));
            Map<String, String> similarSyntaxMap = Maps.newHashMap();
            for (String primarySyntax : primarySyntaxs) {
                List<String> similarSyntaxs = Lists.newArrayList(splitter.split(properties.getProperty("sameSyntax." + primarySyntax)));
                for (String similarSyntax : similarSyntaxs) {
                    similarSyntaxMap.put(similarSyntax, primarySyntax);
                }
            }

            for (Map.Entry<String, Integer> entry : entrySet) {
                try {
                    String content = entry.getKey();
                    MoStatistic moStatistic = new MoStatistic();
                    moStatistic.setContent(content);
                    int count = entry.getValue();
                    logger.debug("Entry: {}-{}", content, count);

                    moStatistic.setCount(BigDecimal.valueOf(count));
                    moProductions.add(moStatistic);

                    try {
                        List<String> tokens =  Lists.newArrayList(Splitter.on(' ').trimResults().omitEmptyStrings().split(content));
                        String commandCode = tokens.get(0);
                        logger.debug("CommandCode: {}", commandCode);

                        String vungMien = "";
                        if (tokens.size() > 1 && !nonLotteryServices.contains(commandCode)) {
                            try {
                                String provinceCode = tokens.get(1);
                                logger.debug("Province Code: {}", provinceCode);
                                vungMien = provinceMap.get(provinceCode).getVungMien();
                            } catch (Exception e) {
                                logger.error("Province Error: {}", content, e);
                                JsfUtil.addErrorMessage("Lỗi vùng", "Ko nhận diện được mã vùng: " + content);
                            }
                        }

                        if (similarSyntaxMap.containsKey(commandCode)) {
                            commandCode = similarSyntaxMap.get(commandCode);
                        }
                        String moSummaryKey;
                        if ("Miền Bắc".equalsIgnoreCase(vungMien)) {
                            moSummaryKey = commandCode + " MB";
                        } else if ("Miền Trung".equalsIgnoreCase(vungMien)) {
                            moSummaryKey = commandCode + " MT";
                        } else if ("Miền Nam".equalsIgnoreCase(vungMien)) {
                            moSummaryKey = commandCode + " MN";
                        } else {
                            if (nonLotteryServices.contains(commandCode)) {
                                moSummaryKey = commandCode;
                            } else {
                                moSummaryKey = commandCode + " MB";
                            }
                        }
                        //lay tong hien tai
                        int moSummaryProduction = count;
                        if (moSummaryMap.containsKey(moSummaryKey)) {
                            moSummaryProduction += moSummaryMap.get(moSummaryKey);
                        }
                        moSummaryMap.put(moSummaryKey, moSummaryProduction);
                    } catch (Exception ex) {
                        JsfUtil.addErrorMessage("Lỗi", ex.getMessage());
                        logger.error("", ex);
                    }
                } catch (Exception ex) {
                    JsfUtil.addErrorMessage("Lỗi", ex.getMessage());
                    logger.error("", ex);
                }
            }

            Set<Map.Entry<String, Integer>> summaryEntrySet = moSummaryMap.entrySet();
            moSummaryProductions = Lists.newArrayListWithCapacity(summaryEntrySet.size());
            for (Map.Entry<String, Integer> entry : summaryEntrySet) {
                try {
                    String content = entry.getKey();
                    MoStatistic moStatistic = new MoStatistic();
                    moStatistic.setContent(content);
                    moStatistic.setCount(BigDecimal.valueOf(entry.getValue()));
                    moSummaryProductions.add(moStatistic);
                } catch (Exception ex) {
                    JsfUtil.addErrorMessage("Lỗi", ex.getMessage());
                    logger.error("", ex);
                }
            }

            Comparator<MoStatistic> comparator = new Comparator<MoStatistic>() {

                @Override
                public int compare(MoStatistic o1, MoStatistic o2) {
                    return syntaxOrders.indexOf(o1.getContent()) - syntaxOrders.indexOf(o2.getContent());
                }
            };
            Collections.sort(moSummaryProductions, comparator);
        } catch (Exception ex) {
            JsfUtil.addErrorMessage("Lỗi", ex.getMessage());
            logger.error("", ex);
        }
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public List<MoStatistic> getMoProductions() {
        return moProductions;
    }

    public List<MoStatistic> getMoSummaryProductions() {
        return moSummaryProductions;
    }

    public List<String> getDeliverProviders() {
        return deliverProviders;
    }

    public void setDeliverProviders(List<String> deliverProviders) {
        this.deliverProviders = deliverProviders;
    }

}
